package com.glodon.paas.consumer.service;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.net.URI;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;

import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.exception.OAuthNotAuthorizedException;
import oauth.signpost.signature.QueryStringSigningStrategy;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import com.glodon.paas.security.oauth1.OAuthConsumerEx;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

/**
 * @author: Don Li
 */
public class SDKTestServlet extends HttpServlet {

    @Value("${api.host}")
    private String apiHost;
    
    @Value("${job.host}")
    private String jobHost;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        resp.setCharacterEncoding("UTF-8");
        Writer writer = resp.getWriter();

        String requestToken = req.getParameter("oauth_token");
        if (requestToken == null || "".equals(requestToken)) {
            writer.write("authorization is denied");
            return;
        }
        
        String uri = req.getParameter("uri");
        String menthodType = req.getParameter("menthodType");
        String body = req.getParameter("body");
        OAuthProvider provider = (OAuthProvider) req.getSession().getAttribute("provider");
        OAuthConsumer consumer = (OAuthConsumer) req.getSession().getAttribute("consumer");
        if(uri==null){
            try {
                // retrieve access token
                provider.retrieveAccessToken(consumer, null);
            } catch (OAuthNotAuthorizedException e) {
                // not authorized
                writer.write("Your reqeuest is denied.");
                return;
            } catch (OAuthException e) {
                throw new ServletException("Fail to retrieve access token", e);
            }
            uri="";
            menthodType="get";
        }
        uri = uri.trim();
        writer.write("<b> PAAS API test <br>");
        writer.write("<b>1: http://"+req.getServerName()+":"+req.getServerPort()+"/account/api/user<br>");
        writer.write("<b>2: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/files/root<br>");
        writer.write("<b>3: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/files/id/{fileId} <br>");
        writer.write("<b>4: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/files/id/{fileId}/sub-files<br>");
        writer.write("<b>5: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/files/id/{fileId}/sub-files/{fileName}<br>");
        writer.write("<b>6: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/files/id/{fileId}/data<br>");
        writer.write("<b>7: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/files/id/{fileId}/data/{revision}<br>");
        writer.write("<b>8: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/files/recycler<br>");
        writer.write("<b>9: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/files/recycler/id/{fileId}<br>");
        writer.write("<b>10: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/files;parentId={parentId};name={folderName}<br>");
        writer.write("<b>11: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/files;parentId={parentId};name={fileName};length={fileLength};chunk={chunk}<br>");
        writer.write("<br>");
        writer.write("<b>-------------------------------------Share File API Test-----------------------------------------------------<br>");
        writer.write("<b>1: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/share/id/{fileId}/email/{email}/privilege/{privilege}<br>");
        writer.write("<b>2: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/share/byme/id/{fileId}<br>");
        writer.write("<b>3: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/share/forme/id/{fileId}<br>");
        
        writer.write("<br>");
        writer.write("<b>--------------------------------------Internal API Test-----------------------------------------------------<br>");
        writer.write("<b>1: http://"+req.getServerName()+":"+req.getServerPort()+"/document/api/internal/files;parentId={parentId};name={folderName};email={email};length={fileLength};chunk={chunk}<br>");
        writer.write("<br>");
        writer.write("<b>------------------------------------- QTO API test ---------------------------------------------------------<br>");
        writer.write("<b>1: GET  "+jobHost+"/qto/job/ <br>");
        writer.write("<b>2: GET  "+jobHost+"/qto/job/{jobId} <br>");
        writer.write("<b>3: POST "+jobHost+"/qto/job/gcl10<br>");
        writer.write("<br>");
        
        writer.write("<b>------------------------------------- Package API test-------------------------------------------------<br>");
        writer.write("<b>1: POST "+jobHost+"/package/job/{type} <br>");
        writer.write("<b>2: GET  "+jobHost+"/package/job/{jobId} <br>");
        writer.write("<b>3: GET  "+jobHost+"/package/seed/{source}/{localId}/{version} <br>");
        writer.write("<b>4: GET  "+jobHost+"/package/job/{jobId}/thumbnail <br>");
        writer.write("<b>5: GET  "+jobHost+"/package/job/{jobId}/mime/{mime} <br>"); 
        writer.write("<b>6: GET  "+jobHost+"/package/job/{jobId}/path/{fileName} <br>"); 
        writer.write("<b>7: GET  "+jobHost+"/package/job/{jobId}/path/resource/{folder}/{fileName} <br>"); 
        writer.write("<b>8: DELETE "+jobHost+"/package/job/{jobId} <br>"); 
        writer.write("<b>-------------------------------------------------------------------------------------------------------<br>");
        writer.write("<form method=\"GET\" action=\"callback\" >");
        writer.write("<input type=\"hidden\" value=\""+requestToken+"\" name=\"oauth_token\"/>");
        writer.write("<input type=\"text\" value=\""+uri+ "\" name=\"uri\" size=\"100px\" />");
        writer.write("<input type=\"text\" value=\""+menthodType+ "\" name=\"menthodType\" size=\"20px\" />");
        writer.write("<input value=\"submit\" type=\"submit\"/>");
        writer.write("<textarea rows=\"5\" cols=\"120\" name=\"body\"></textarea> <br>" );
        writer.write("</form>");
        if(StringUtils.isEmpty(uri)){
        	return;
        }

        try {
        	if(uri.indexOf("/internal/")>0){
        		if("POST".equalsIgnoreCase(menthodType)){
            		if(uri.indexOf("chunk")>0){
            			//create file
            			createFileInternal(uri, writer);
            		}
            		else{
            			//create folder
            			postInternal(uri, writer);
            		}
                }
                else if("DELETE".equalsIgnoreCase(menthodType)){
                	deleteInternal(uri, writer);
                }
                else if("GET".equalsIgnoreCase(menthodType)){
                	queryInternal(uri, writer);
                }
        	}
        	else{
        		if("POST".equalsIgnoreCase(menthodType)){
            		if(uri.indexOf("chunk")>0){
            			//create file
            			createFile(uri, consumer, writer);
            		}
            		else{
            			//create folder
            			post(uri, consumer, writer, body);
            		}
                }
                else if("DELETE".equalsIgnoreCase(menthodType)){
                	delete(uri, consumer, writer);
                }
                else if("GET".equalsIgnoreCase(menthodType)){
                	query(uri, consumer, writer);
                }
        	}
        } catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
            writer.close();
        }
    }

    private void queryInternal(String urlStr, Writer writer) throws Exception {
       
         WebResource resource = Client.create().resource(urlStr);
  	 
         ClientResponse c = resource.type(MediaType.APPLICATION_OCTET_STREAM).get(ClientResponse.class);
	   	 writer.write("<br>");
	   	 writer.write(c.getEntity(String.class));
	   	 writer.write("<br>"); 
    }
    
    private void postInternal(String urlStr, Writer writer) throws IOException, OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {	
    	 writer.write("<br>");
         WebResource resource = Client.create().resource(urlStr);
	   	 ClientResponse c = resource.type(MediaType.APPLICATION_OCTET_STREAM).post(ClientResponse.class);
	   	 writer.write(c.getEntity(String.class));
	   	 writer.write("<br>");
    }
    private void deleteInternal(String urlStr, Writer writer) throws IOException, OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {	
      	 writer.write("<br>");
         WebResource resource = Client.create().resource(urlStr);
   	   	 ClientResponse c = resource.type(MediaType.APPLICATION_JSON_TYPE).delete(ClientResponse.class);
   	   	 writer.write(c.getEntity(String.class));
   	   	 writer.write("<br>");
      }

       private void createFileInternal(String urlStr, Writer writer) throws OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException, IOException {
       	byte[] bytes = "Data of Sample File".getBytes();
        InputStream data = new ByteArrayInputStream(bytes);
        WebResource resource = Client.create().resource(urlStr.replace("{fileLength}", String.valueOf(bytes.length)));
           
   	   	 ClientResponse c = resource.type(MediaType.APPLICATION_OCTET_STREAM).post(ClientResponse.class,data);
   	   	 writer.write("<br>");
   	   	 writer.write(c.getEntity(String.class));
   	   	 writer.write("<br>"); 
       }
       
    private void query(String urlStr, OAuthConsumer consumer, Writer writer) throws Exception {
    	OAuthConsumerEx myConsumer = (OAuthConsumerEx)consumer;
   	    String signedUrl = myConsumer.sign(urlStr);
       
         WebResource resource = Client.create().resource(signedUrl);
  	 
         ClientResponse c = resource.type(MediaType.APPLICATION_JSON_TYPE).get(ClientResponse.class);
	   	 writer.write("<br>");
	   	 writer.write(c.getEntity(String.class));
	   	 writer.write("<br>"); 
    }
    
    private void post(String urlStr, OAuthConsumer consumer, Writer writer, String body) throws IOException, OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {	
    	 writer.write("<br>");
    	 OAuthConsumerEx myConsumer = (OAuthConsumerEx)consumer;
    	 myConsumer.setSigningStrategy(new QueryStringSigningStrategy());
    	 String signedUrl = myConsumer.sign(urlStr, "POST");
         WebResource resource = Client.create().resource(signedUrl);
	   	 ClientResponse c = resource.type(MediaType.APPLICATION_OCTET_STREAM).post(ClientResponse.class, body);
	   	 writer.write(c.getEntity(String.class));
	   	 writer.write("<br>");
    }
    
    private void delete(String urlStr, OAuthConsumer consumer, Writer writer) throws IOException, OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {	
   	 writer.write("<br>");
   	 OAuthConsumerEx myConsumer = (OAuthConsumerEx)consumer;
   	 myConsumer.setSigningStrategy(new QueryStringSigningStrategy());
   	 String signedUrl = myConsumer.sign(urlStr, "DELETE");
        WebResource resource = Client.create().resource(signedUrl);
	   	 ClientResponse c = resource.type(MediaType.APPLICATION_JSON_TYPE).delete(ClientResponse.class);
	   	 writer.write(c.getEntity(String.class));
	   	 writer.write("<br>");
   }

    private void createFile(String urlStr, OAuthConsumer consumer, Writer writer) throws OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException, IOException {
    	byte[] bytes = "Data of Sample File".getBytes();
    	URI uri = UriBuilder.fromUri(urlStr.replace("{fileLength}", String.valueOf(bytes.length))).build();
    	
    	OAuthConsumerEx myConsumer = (OAuthConsumerEx)consumer;
    	myConsumer.setSigningStrategy(new QueryStringSigningStrategy());
   	    String signedUrl = myConsumer.sign(uri.toString(), "POST");
        
        InputStream data = new ByteArrayInputStream(bytes);
        WebResource resource = Client.create().resource(signedUrl);
        
	   	 ClientResponse c = resource.type(MediaType.APPLICATION_OCTET_STREAM).post(ClientResponse.class,data);
	   	 writer.write("<br>");
	   	 writer.write(c.getEntity(String.class));
	   	 writer.write("<br>"); 
    }
}
